#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@Date:2022/07/18 16:54:45
'''
import sys
sys.path.append('.')
from sqlalchemy import distinct, or_, and_, desc, asc
from sqlalchemy.sql import func
from db_logic.db_base import Repository
from models.medicament_models import EntityMedicament, EntityMedicamentRecord, EntityMedicamentTemplate
from models.client_models import EntityClient
from models.user_models import EntityUser
from db_logic.meidcament_variety import BllMedicamentVariety
from Common.Utils import Utils, DrugStatus, DrugRecordType



#药剂流程业务逻辑类
class BllMedicament(Repository):

    def __init__(self, entityType=EntityMedicament):
        return super().__init__(entityType)

    def update(self, entity):
        entity.remark30 = '0'
        return super().update(entity)

    # 获取离保质期最近的同类药剂
    def getDrugNearExpired(self, varietyId, customerId):
        drugList = self.findList(
            and_(
                EntityMedicament.status == DrugStatus.Normal,
                EntityMedicament.variety_id == varietyId
                )).order_by(EntityMedicament.expiration_date).limit(1)
        return drugList.first()

    # 根据条码获取试剂详细信息
    def get_bar_code_drug_info(self, bar_code):
        return self.execute(f"select * from rms_medicament where bar_code='{bar_code}'").fetchall()

        # 获取库存余量
    def get_drug_surplus(self, client_id, func_type, page_param):
        # 动态添加查询条件
        where_base = ""
        if client_id:
            where_base = f" client_id='{client_id}'"
        if func_type:
            if where_base:
                where_base += " and "
            where_base += f" func_type='{func_type}'"
        if where_base:
            where_base = f" where {where_base} "
        sql_all = f"""
            select 
                `name`, english_name, cas_number, speci, net_weight_unit, purity, manufacturer,
                sum(CASE WHEN `status`=1 THEN 1 ELSE 0 END) surplus_number 
            from rms_medicament {where_base} GROUP BY `name`, speci, purity order by put_in_date desc
        """
        # 查询页总数
        try:
            total_count = len(self.execute(sql_all).fetchall())
        except Exception:
            total_count = 0
        # count_sql = f"SELECT count(*) FROM rms_medicament %s GROUP BY `name`, cas_number, purity" % where_base
        page_param.totalRecords = total_count
        # 调用分页组装sql
        sql_all = Utils.sql_paging_assemble(sql_all, page_param)
        data_list = self.execute(sql_all).fetchall()

        return data_list

    # 获取试剂库存消耗
    def get_drug_stock_use_classify(self, func_type):
        sql_all = f"""
        select count(medicament_id) count_number, `status` from rms_medicament where func_type='{func_type}' GROUP BY `status` order by put_in_date desc
        """
        # 查看分组数据
        data = self.execute(sql_all).fetchall()
        # 计算总数
        data_number = sum([i[0] for i in data])
        data_li = Utils.msyql_table_model(data)
        data_list = []
        # 计算百分比，组装数据
        type_num = []
        for i in data_li:
            new_dict = {
                # "ratio": str(round(i["count_number"] / data_number,2) * 100) + "%"
                "ratio": Utils.classify(i['count_number'], data_number)
            }
            new_dict.update(i)
            type_num.append(str(i["status"]))
            data_list.append(new_dict)
        set_num_li = list(set(["1", "2", "3"]).difference(set(type_num)))
        for i in set_num_li:
            data_list.append(
                {
                    "status": int(i),
                    "rotio": "0%",
                    "count_number": "0"
                }
            )
        return data_list, data_number



    #获取药剂列表
    def getDrugList(self, customerId, keyWord, pageParam):
        keyWord = '%' + keyWord + '%'
        orm_query = self.findList().filter(
            EntityMedicament.customer_id == customerId
            ).filter(
                # or_(EntityMedicament.RFID.like(keyWord), EntityMedicament.name.like(keyWord))
                or_(EntityMedicament.RFID.like(keyWord), EntityMedicament.name.like(keyWord))
                ).order_by(
                    # desc(EntityMedicament.PutInStorageDate)
                    desc(EntityMedicament.put_in_date)
                    )
        return self.queryPage(orm_query, pageParam)

    # 试剂管理
    def get_drug_list(self, client_id, seach_word, b_code, func_type, page_param):
        filter_base = ""
        if client_id:
            filter_base += f" client_id='{client_id}' "
        if seach_word:
            seach_word = f"%{seach_word}%"
            if filter_base:
                filter_base += " and "
            filter_base += f" (`name` like '{seach_word}' or english_name like '{seach_word}') "
        # 搜索bar_code
        # if b_code:
        #     if len(b_code) > 10:
        #         new_code = ''
        #         for i in range(int(len(b_code) / 2)):
        #             new_code = b_code[i*2:(i+1)*2] + new_code
        #     else:
        #         new_code = b_code
        #     new_code = f"%{new_code}%"
        #     if filter_base:
        #         filter_base += " and "
        #     filter_base += f" bar_code like '{new_code}' "
        if filter_base:
            if len(seach_word) > 10:
                new_code = ''
                for i in range(int(len(seach_word) / 2)):
                    new_code = seach_word[i*2:(i+1)*2] + new_code
            else:
                new_code = seach_word
            new_code = f"%{new_code}%"
            if filter_base:
                filter_base += " and "
            filter_base += f" (bar_code like '{new_code}' or bar_code like '{seach_word}' )"
        if func_type:
            if filter_base:
                filter_base += " and "
            filter_base += f" func_type='{func_type}'"

        if filter_base:
            filter_base = f" where {filter_base}"
        sql_all = f"""
            select * from rms_medicament {filter_base} order by put_in_date desc
        """
        try:
            count_number = len(self.execute(sql_all).fetchall())
        except Exception:
            count_number = 0
        page_param.totalRecords=count_number
        page_sql = Utils.sql_paging_assemble(sql_all, page_param)
        return self.execute(page_sql).fetchall()
    
    # 选择药剂入库--试剂详情
    def get_drug_info_distinct_list(self, seach_word, func_type, page_param, client_id=None):
        # 动态添加查询条件
        filter_base = ""
        if client_id:
            filter_base += f"client_id='{client_id}'"
        if seach_word:
            seach_word = f"%{seach_word}%"
            if filter_base:
                filter_base += " and"
            filter_base += f" (`name` like '{seach_word}' or english_name like '{seach_word}') "
        if func_type:
            if filter_base:
                filter_base += " and"
            filter_base += f" func_type='{func_type}' "
        if filter_base:
            filter_base = f" where {filter_base}"

        sql_all = f"""
        select * from rms_medicament {filter_base}  group by `name`, purity, speci order by put_in_date desc
        """
        try:
            count_number = len(self.execute(sql_all).fetchall())
        except Exception:
            count_number = 0 
        page_param.totalRecords = count_number
        # 分页sql
        page_sql = Utils.sql_paging_assemble(sql_all, page_param)

        return self.execute(page_sql).fetchall()

    # 药剂入库
    def drugPutIn(self, entityDrug=EntityMedicament(), entityClient=EntityClient(), entityUser=EntityUser()):

        entityDrugRecord = EntityMedicamentRecord(
            customer_id=entityClient.customer_id,
            client_id=entityClient.client_id,
            client_code=entityClient.client_code,
            variety_id=entityDrug.variety_id,
            medicament_id=entityDrug.medicament_id,
            price=entityDrug.price,
            record_type=DrugRecordType.PutIn,
            record_remain=float(entityDrug.remain),

            is_empty=0,
            create_date=Utils.get_str_datetime(),
            create_user_id=entityUser.user_id,
            create_user_name=entityUser.real_name,

        )

        # 创建事务
        self.beginTrans()
        entityDrug.remark30 = '0'
        self.session.add(entityDrug)
        if entityDrug.status == 1:
            self.session.add(entityDrugRecord)
        boolean_ = self.commitTrans()
        if boolean_ is None:
            return True
        return boolean_
    # 药剂领用
    def drugUse(self, entityDrug=EntityMedicament(), entityClient=EntityClient(), entityUser=EntityUser()):
        #创建事务
        self.beginTrans()
        entityDrug.remark30 = '0'
        self.session.merge(entityDrug)
        entityDrugRecord = EntityMedicamentRecord(
            customer_id=entityClient.customer_id,
            client_id=entityClient.client_id,
            client_code=entityClient.client_code,
            variety_id=entityDrug.variety_id,
            medicament_id=entityDrug.medicament_id,
            price=entityDrug.price,
            record_type=DrugRecordType.Use,
            is_empty=0,
            record_remain=float(entityDrug.remain),
            create_date=Utils.get_str_datetime(),
            create_user_id=entityUser.user_id,
            create_user_name=entityUser.real_name,

        )

        self.session.add(entityDrugRecord)
        entityVariety = BllMedicamentVariety().findEntity(entityDrug.variety_id)
        entityVariety.normal_count -= 1
        entityVariety.use_count += 1
        self.session.merge(entityVariety)
        self.commitTrans()

    # 药剂归还
    def drugReturn(self, entityDrug=EntityMedicament(), entityClient=EntityClient(), entityUser=EntityUser()):
        #创建事务
        self.beginTrans()
        entityDrug.remark30 = '0'
        self.session.merge(entityDrug)

        drug = BllMedicament().findEntity(entityDrug.medicament_id)
        lastRemain = float(drug.remain)

        entityDrugRecord = EntityMedicamentRecord(
            customer_id=entityClient.customer_id,
            client_id=entityClient.client_id,
            client_code=entityClient.client_code,
            variety_id=entityDrug.variety_id,
            medicament_id=entityDrug.medicament_id,
            price=entityDrug.price,
            use_quantity=float(lastRemain) - float(entityDrug.remain if entityDrug.remain else 0),
            record_type=DrugRecordType.Return,
            record_remain=float(entityDrug.remain),
            is_empty=1 if(entityDrug.status == DrugStatus.Empty) else 0,
            create_date=Utils.get_str_datetime(),
            create_user_id=entityUser.user_id,
            create_user_name=entityUser.real_name,

        )
        self.session.add(entityDrugRecord)
        entityVariety = BllMedicamentVariety().findEntity(entityDrug.variety_id)
        if(entityDrug.remain != 0):
            entityVariety.normal_count += 1
        else:
            entityVariety.empty_count += 1
        entityVariety.use_count -= 1
        self.session.merge(entityVariety)

        self.commitTrans()

    # 获取领用和归还页面列表
    def drug_use_return(self, status, func_type, page_param):
        sql_all = f"""
            select * from rms_medicament  where status={status} and func_type='{func_type}' order by by_user_date desc
        """
        try:
            count_number = len(self.execute(sql_all).fetchall())
        except:
            count_number = 0
        page_param.totalRecords = count_number
        sql_all = Utils.sql_paging_assemble(sql_all, page_param)
        data_list = self.execute(sql_all).fetchall()
        return data_list


    # 获取库存信息总览
    def get_stock_all_info(self, page_param, func_type, name=None):
        filter_base = ""
        if name:
            filter_base = f" `name` LIKE '%{name}%'"
        if func_type:
            if filter_base:
                filter_base += " and "
            filter_base += f" func_type='{func_type}' "
        if filter_base:
            filter_base = f" where {filter_base}"
        sql_all =f"""
        select DISTINCT 
        `name`, speci, cas_number,net_weight_unit, purity, 
        manufacturer, distributor, net_weight, net_weight_unit,
        client_id,

            sum(CASE WHEN `status`=1 THEN 1 ELSE 0 END) count_number, 
            sum(CASE WHEN `status`=1 THEN remain ELSE 0 END) sum_remain 
            FROM rms_medicament {filter_base} GROUP BY `name`, speci, purity order by put_in_date desc
        """
        # 首次查询，判断长度，做分页使用
        try:
            count_number = len(self.execute(sql_all).fetchall())
        except Exception:
            count_number = 0
        # 组件分页参数，返回分页后数据
        if page_param:
            page_param.totalRecords = count_number
            sql_all = Utils.sql_paging_assemble(sql_all, page_param)
        return self.execute(sql_all).fetchall()

    #获取所有药剂列表
    def getAllDrugList(self, search_word, manufacturer, start_time, end_time, func_type,  page_param, customer_id=None, client_id=None, client_speci=None):
        # (Name like :searchWord or BarCode like :searchWord or EnglishName like :searchWord)
        filter_base = ""
        if customer_id:
            filter_base = f"customer_id='{customer_id}'"
        if client_id:
            if filter_base:
                filter_base += " and "
            filter_base += f"client_id='{client_id}'"
        # 名称搜索
        if search_word:
            seach_w = f"%{search_word}%"
            if filter_base:
                filter_base += " and "
            bar_code, new_code = Utils.get_bar_code_reverse(search_word)
            filter_base += f" `name` like '{seach_w}' or english_name like '{seach_w}' or manufacturer like '{seach_w}' "
            filter_base += f" or  bar_code='{bar_code}' or bar_code='{new_code}' "
        # 厂商搜索
        if manufacturer:
            manufacturer = f"%{manufacturer}%"
            if filter_base:
                filter_base += " and "
            filter_base += f"manufacturer like '{manufacturer}'"
        # 时间范围搜索
        if start_time and end_time:
            if filter_base:
                filter_base += " and "
            filter_base += f"put_in_date >= '{start_time}' and put_in_date<='{end_time}'"
        # 管理模块区分
        if func_type:
            if filter_base:
                filter_base += " and "
            filter_base += f" func_type={func_type}"

        if filter_base:
            filter_base = "where " + filter_base
        # select * from rms_medicament {filter_base}
        #TODO 添加房间筛选
        filter_base1 = ""
        # if client_speci:
        #     filter_base1 += f"where client_speci='{client_speci}'"
        sql_all = f"""
            select a.*,b.client_name from (
                select * from rms_medicament {filter_base}
            ) a LEFT JOIN(
                select client_id,client_name from rms_client {filter_base1}
            ) b on a.client_id=b.client_id
            where client_name is not null
            order by put_in_date desc
        """
        # manufacturer = manufacturer,
        # start_time = start_time,
        # end_time = end_time,
        # 动态添加查询条件
        # 获取数量做分页
        try:
            count_number= len(self.execute(sql_all).fetchall())
        except Exception:
            count_number = 0
        
        # 进行分页sql拼接
        if page_param:
            page_param.totalRecords = count_number
            sql_all = Utils.sql_paging_assemble(sql_all, page_param)
        
        return self.execute(sql_all).fetchall()

    # 入库、领用、归还记录
    def drug_show_type_info(self, record_type, start_time, end_time, put_in_user_name, name, func_type, statue_type, page_param):
        filter_base1 = f" WHERE record_type={record_type} "
        if put_in_user_name:
            filter_base1 += f" and create_user_name like '%{put_in_user_name}%'"
        if start_time and end_time:
            filter_base1 += f" and create_date >= '{start_time}' and create_date <= '{end_time}'"
        
        filter_base2 = ''
        if name:
            name = f"%{name}%"
            filter_base2 += f" (`name` like '{name}' or english_name like '{name}') "

        if statue_type:
            if filter_base2:
                filter_base2 += " and "
            filter_base2 = f"  `status`={statue_type}"
        
        if func_type:
            if filter_base2:
                filter_base2 += " and "
            filter_base2 += f" func_type='{func_type}' "
        if filter_base2:
            filter_base2 = f" where {filter_base2}"
        sql_all = f"""
            select 
                `name`, english_name, bar_code, purity, 
                cas_number, speci, use_quantity, `status`, 
                create_date, create_user_name, a.client_id, client_code, client_name, unit_code
	        from (select * from rms_medicament_record {filter_base1}
            ) as a LEFT JOIN(
			select 
			    medicament_id, `name`, english_name, 
                bar_code, purity, speci, cas_number, 
                net_weight, remain, `status`, 
                by_user_date, by_user_name, unit_code  
            FROM rms_medicament {filter_base2}
            ) as b on a.medicament_id=b.medicament_id  
            LEFT JOIN(select client_id,client_name from rms_client) c on a.client_id=c.client_id
            where name is not null GROUP BY create_date desc
        """
        try:
            count_number = len(self.execute(sql_all).fetchall())
        except Exception:
            count_number = 0
        if page_param:
            page_param.totalRecords = count_number
            sql_all = Utils.sql_paging_assemble(sql_all, page_param)
        return self.execute(sql_all).fetchall()

    def client_room_number(self):
        sql_all = """
            select 
                sum(record_num) value, client_speci name  
            from (
	            select medicament_id, client_id from rms_medicament
	        ) as a LEFT JOIN(
		        SELECT count(*) record_num, medicament_id FROM rms_medicament_record WHERE record_type=2 GROUP BY medicament_id
		    ) as b on  a.medicament_id=b.medicament_id LEFT JOIN 
	            rms_client as c on a.client_id=c.client_id 
            GROUP BY client_speci 
            HAVING client_speci is not null
        """
        return self.execute(sql_all).fetchall()

    # 手动输入入库模板时，获取分组后的试剂信息列表
    def drug_group_info_list(self):
        sql_all = f"""
            select 
                medicament_id, name as value, english_name, 
                cas_number, purity, production_date, 
                expiration_date, manufacturer,distributor,speci,
                net_weight_unit, total from rms_medicament 
            group by `name`, speci, purity 
        """
        return self.execute(sql_all).fetchall()
    
    # 库存盘点获取分组后的试剂信息数据
    def get_drug_stock_info(self, client_id):
        sql_all = f"""
            select count(*) stock_num, `name`, speci, purity from rms_medicament where client_id= '{client_id}' group by `name`, speci, purity 
        """
        return self.execute(sql_all).fetchall()


    def inster_log_shiji(self):
        import random
        name_list = ["砷", "硫酸", "氧化钠"]
        obj_list = []
        for i in range(100):
            obj = EntityMedicament(
                bar_code= 10000 + i,
                client_id='1c39cb24-07f8-11ed-abd4-f47b094925e1',
                client_code="12345",
                name=random.choice(name_list),
                production_date=Utils.get_str_datetime(),
                shelf_life=10,
                remain=100,
                total=500,
                net_weight_unit="g",
                net_weight=100,
                purity="国标",
                put_in_date=Utils.get_str_datetime(),
                put_in_user_id='4cea74ee-0d8b-11ed-943e-f47b094925e1',
                put_in_user_name="admin",
                status=random.randint(1,3)
            )
            obj_list.append(obj)
        self.insert_many(obj_list)

# if __name__ == '__main__':
#     from db_logic.medicament import BllMedicament
#     from Common.Utils import PageParam
#     page_param = PageParam(1, 10)
#     data = BllMedicament().inster_log_shiji()
#     print(data)
    # values= {}
    # page = values.get("page", 1)
    # page_size = values.get("page_size", 10)
    # record_type = values.get("record_type", 1)
    # put_in_user_name = values.get("put_in_user_name")
    # name = values.get("name")
    # start_time = values.get("start_time")
    # end_time = values.get("end_time")
    # page_param = PageParam(page, page_size)
    # typ_dic = BllMedicament().drug_show_type_info(record_type=record_type, put_in_user_name=put_in_user_name,
    #                                               name=name, start_time=start_time, end_time=end_time, page_param=page_param
    #                                               )
    # print(typ_dic)

    
